home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 5 / Example 5.8 / mesh.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-01  |  6.2 KB  |  263 lines

  1. #include "mesh.h"
  2.  
  3. const DWORD ObjectVertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
  4.  
  5. MESH::MESH()
  6. {
  7.     m_pDevice = NULL;
  8.     m_pMesh = NULL;
  9.     m_pProgressiveMesh = NULL;
  10. }
  11.  
  12. MESH::MESH(char fName[], IDirect3DDevice9* Dev)
  13. {
  14.     m_pDevice = Dev;
  15.     m_pMesh = NULL;
  16.     m_pProgressiveMesh = NULL;
  17.     Load(fName, m_pDevice);
  18. }
  19.  
  20. MESH::~MESH()
  21. {
  22.     Release();
  23. }
  24.  
  25. HRESULT MESH::Load(char fName[], IDirect3DDevice9* Dev)
  26. {
  27.     m_pDevice = Dev;
  28.  
  29.     try
  30.     {
  31.         //Set white material
  32.         m_white.Ambient = m_white.Specular = m_white.Diffuse  = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
  33.         m_white.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
  34.         m_white.Power = 1.0f;
  35.  
  36.         Release();
  37.  
  38.         //Load new mesh
  39.         ID3DXBuffer * adjacencyBfr = NULL;
  40.         ID3DXBuffer * materialBfr = NULL;
  41.         DWORD noMaterials = NULL;
  42.  
  43.         if(FAILED(D3DXLoadMeshFromX(fName, D3DXMESH_MANAGED, m_pDevice,    &adjacencyBfr, &materialBfr, NULL, &noMaterials, &m_pMesh)))
  44.             return E_FAIL;
  45.  
  46.         D3DXMATERIAL *mtrls = (D3DXMATERIAL*)materialBfr->GetBufferPointer();
  47.  
  48.         for(int i=0;i<noMaterials;i++)
  49.         {
  50.             m_materials.push_back(mtrls[i].MatD3D);
  51.  
  52.             if(mtrls[i].pTextureFilename != NULL)
  53.             {
  54.                 char textureFileName[90];
  55.                 strcpy(textureFileName, "objects/");
  56.                 strcat(textureFileName, mtrls[i].pTextureFilename);
  57.                 IDirect3DTexture9 * newTexture = NULL;
  58.                 D3DXCreateTextureFromFile(m_pDevice, textureFileName, &newTexture);            
  59.                 m_textures.push_back(newTexture);
  60.             }
  61.             else m_textures.push_back(NULL);
  62.         }
  63.  
  64.         //Release buffers
  65.         adjacencyBfr->Release();
  66.         materialBfr->Release();
  67.  
  68.         //Create progressive mesh        
  69.         DWORD *adj = new DWORD[m_pMesh->GetNumFaces() * 3];
  70.         m_pMesh->GenerateAdjacency(0.0f, adj);        //Load Adjancency Table
  71.  
  72.         if(FAILED(D3DXGeneratePMesh(m_pMesh, adj, NULL, NULL,
  73.                         1, D3DXMESHSIMP_FACE, &m_pProgressiveMesh)))
  74.         {
  75.             debug.Print("Failed to create progressive mesh");
  76.             exit(0);
  77.         }        
  78.  
  79.         delete [] adj;
  80.  
  81.         m_pProgressiveMesh->SetNumFaces(m_pMesh->GetNumFaces());
  82.  
  83.  
  84.     }
  85.     catch(...)
  86.     {
  87.         debug.Print("Error in MESH::Load()");
  88.         return E_FAIL;
  89.     }
  90.  
  91.     return S_OK;
  92. }
  93.  
  94. void MESH::Render()
  95. {
  96.     if(m_pMesh != NULL)
  97.         for(int i=0;i<m_materials.size();i++)
  98.         {    
  99.             if(m_textures[i] != NULL)m_pDevice->SetMaterial(&m_white);
  100.             else m_pDevice->SetMaterial(&m_materials[i]);
  101.             m_pDevice->SetTexture(0,m_textures[i]);
  102.             m_pMesh->DrawSubset(i);
  103.         }    
  104. }
  105.  
  106. void MESH::SetLOD(int numFaces)
  107. {
  108.     if(m_pProgressiveMesh == NULL)return;
  109.     m_pProgressiveMesh->SetNumFaces(numFaces);        //Set LOD
  110. }
  111.  
  112. void MESH::RenderProgressive()
  113. {
  114.     if(m_pProgressiveMesh != NULL)
  115.         for(int i=0;i<m_materials.size();i++)
  116.         {    
  117.             if(m_textures[i] != NULL)m_pDevice->SetMaterial(&m_white);
  118.             else m_pDevice->SetMaterial(&m_materials[i]);
  119.             m_pDevice->SetTexture(0,m_textures[i]);
  120.             m_pProgressiveMesh->DrawSubset(i);
  121.         }
  122. }
  123.  
  124. void MESH::Release()
  125. {
  126.     //Clear old mesh...
  127.     if(m_pMesh != NULL)
  128.     {
  129.         m_pMesh->Release();
  130.         m_pMesh = NULL;
  131.     }
  132.  
  133.     if(m_pProgressiveMesh != NULL)
  134.     {
  135.         m_pProgressiveMesh->Release();
  136.         m_pProgressiveMesh = NULL;
  137.     }
  138.  
  139.     //Clear textures and materials
  140.     for(int i=0;i<m_textures.size();i++)
  141.         if(m_textures[i] != NULL)
  142.             m_textures[i]->Release();
  143.  
  144.     m_textures.clear();
  145.     m_materials.clear();    
  146. }
  147.  
  148. MESHINSTANCE::MESHINSTANCE()
  149. {
  150.     m_pMesh = NULL;
  151.     m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  152.     m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
  153. }
  154.  
  155. MESHINSTANCE::MESHINSTANCE(MESH *meshPtr)
  156. {
  157.     m_pMesh = meshPtr;
  158.     m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  159.     m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
  160. }
  161.  
  162. D3DXMATRIX MESHINSTANCE::GetWorldMatrix()
  163. {
  164.     D3DXMATRIX p, r, s;
  165.     D3DXMatrixTranslation(&p, m_pos.x, m_pos.y, m_pos.z);
  166.     D3DXMatrixRotationYawPitchRoll(&r, m_rot.y, m_rot.x, m_rot.z);
  167.     D3DXMatrixScaling(&s, m_sca.x, m_sca.y, m_sca.z);
  168.  
  169.     D3DXMATRIX world = s * r * p;
  170.     return world;
  171. }
  172.  
  173. void MESHINSTANCE::Render()
  174. {
  175.     if(m_pMesh != NULL)
  176.     {
  177.         m_pMesh->m_pDevice->SetTransform(D3DTS_WORLD, &GetWorldMatrix());
  178.         m_pMesh->Render();
  179.     }
  180. }
  181.  
  182. void MESHINSTANCE::SetLOD(int numFaces)
  183. {
  184.     if(m_pMesh != NULL)
  185.         m_pMesh->SetLOD(numFaces);
  186. }
  187.  
  188. void MESHINSTANCE::RenderProgressive()
  189. {
  190.     if(m_pMesh != NULL)
  191.     {
  192.         m_pMesh->m_pDevice->SetTransform(D3DTS_WORLD, &GetWorldMatrix());
  193.         m_pMesh->RenderProgressive();
  194.     }
  195. }
  196.  
  197. BBOX MESHINSTANCE::GetBoundingBox()
  198. {
  199.     if(m_pMesh == NULL || m_pMesh->m_pMesh == NULL)return BBOX();
  200.     
  201.     if(m_pMesh->m_pMesh->GetFVF() != ObjectVertex::FVF)        // XYZ and NORMAL and UV
  202.         return BBOX();
  203.  
  204.     BBOX bBox(D3DXVECTOR3(-10000.0f, -10000.0f, -10000.0f),
  205.               D3DXVECTOR3(10000.0f, 10000.0f, 10000.0f));
  206.     D3DXMATRIX World = GetWorldMatrix();
  207.  
  208.     //Lock vertex buffer of the object
  209.     ObjectVertex* vertexBuffer = NULL;
  210.     m_pMesh->m_pMesh->LockVertexBuffer(0,(void**)&vertexBuffer);
  211.  
  212.     //For each vertex in the mesh
  213.     for(int i=0;i<m_pMesh->m_pMesh->GetNumVertices();i++)
  214.     {
  215.         //Transform vertex to world space using the MESHINSTANCE
  216.         //world matrix, i.e. the position, rotation and scale
  217.         D3DXVECTOR3 pos;
  218.         D3DXVec3TransformCoord(&pos, &vertexBuffer[i]._pos, &World);
  219.  
  220.         // Check if the vertex is outside the bounds
  221.         // if so, then update the bounding volume
  222.         if(pos.x < bBox.min.x)bBox.min.x = pos.x;
  223.         if(pos.x > bBox.max.x)bBox.max.x = pos.x;
  224.         if(pos.y < bBox.min.y)bBox.min.y = pos.y;
  225.         if(pos.y > bBox.max.y)bBox.max.y = pos.y;
  226.         if(pos.z < bBox.min.z)bBox.min.z = pos.z;
  227.         if(pos.z > bBox.max.z)bBox.max.z = pos.z;
  228.     }
  229.  
  230.     m_pMesh->m_pMesh->UnlockVertexBuffer();
  231.  
  232.     return bBox;
  233. }
  234.  
  235. BSPHERE MESHINSTANCE::GetBoundingSphere()
  236. {
  237.     if(m_pMesh == NULL || m_pMesh->m_pMesh == NULL)return BSPHERE();
  238.     if(m_pMesh->m_pMesh->GetFVF() != ObjectVertex::FVF)        // XYZ and NORMAL and UV
  239.         return BSPHERE();
  240.  
  241.     BBOX bBox = GetBoundingBox();
  242.     BSPHERE bSphere;
  243.     D3DXMATRIX World = GetWorldMatrix();
  244.     bSphere.center = (bBox.max + bBox.min) / 2.0f;
  245.  
  246.     ObjectVertex* vertexBuffer = NULL;
  247.     m_pMesh->m_pMesh->LockVertexBuffer(0,(void**)&vertexBuffer);
  248.  
  249.     //Get radius
  250.     for(int i=0;i<m_pMesh->m_pMesh->GetNumVertices();i++)
  251.     {
  252.         D3DXVECTOR3 pos;
  253.         D3DXVec3TransformCoord(&pos, &vertexBuffer[i]._pos, &World);
  254.  
  255.         float l = D3DXVec3Length(&(pos - bSphere.center));
  256.         if(l > bSphere.radius)
  257.             bSphere.radius = l;
  258.     }
  259.  
  260.     m_pMesh->m_pMesh->UnlockVertexBuffer();
  261.  
  262.     return bSphere;
  263. }